import { isObject } from "../utils";
import {
  mutableHandler,
  readonlyHandler,
  shallowHandler,
  shallowReadonlyHandler,
} from "./baseHandlers";

import { isRef } from "./ref";

export const enum ReactiveFlags {
  IS_REACTIE = "__v_isReactive",
  IS_READONLY = "__v_isReadonly",
  RAW = "__v_raw",
}

export const reactiveMap = new WeakMap();
export const readonlyMap = new WeakMap();
export const shallowMap = new WeakMap();
export const shallowReadonlyMap = new WeakMap();

export function reactive(value: any) {
  return createReactiveObject(value, reactiveMap, mutableHandler);
}

export function readonly(value: any) {
  return createReactiveObject(value, readonlyMap, readonlyHandler);
}

export function shallow(value: any) {
  return createReactiveObject(value, shallowMap, shallowHandler);
}

export function shallowReadonly(value: any) {
  return createReactiveObject(
    value,
    shallowReadonlyMap,
    shallowReadonlyHandler
  );
}

export function isProxy(value) {
  return isReactive(value) || isRef(value) || isReadonly(value);
}

export function isReadonly(value) {
  return !!value[ReactiveFlags.IS_READONLY];
}

export function isReactive(value) {
  return !!value[ReactiveFlags.IS_REACTIE];
}

export function createReactiveObject(
  target: Object,
  proxyMap: WeakMap,
  handler
) {
  if (!isObject(target)) {
    return target;
  }

  const existingProxy = proxyMap.get(target);
  if (existingProxy) {
    return existingProxy;
  }

  const proxy = new Proxy(target, handler);

  proxyMap.set(target, proxy);

  return proxy;
}
